﻿using Leeder.Logger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TitaniumAS.Opc.Client.Common;
using TitaniumAS.Opc.Client.Da;

namespace NewAndong.Handle
{
    public class OpcHelper
    {

        /// <summary>
        /// 日志
        /// </summary>
        public LogOperate LogObj => Log.GetLogger(this.GetType());

        /// <summary>
        /// OPC连接状态
        /// </summary>
        public bool opcState = false;
        /// <summary>
        /// 是否自动断开连接
        /// </summary>
        bool isClose = false;
        /// <summary>
        /// opc服务
        /// </summary>
        public OpcDaServer opcServer { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public OpcHelper()
        {

        }

        /// <summary>
        /// 转换OPC值为整型
        /// </summary>
        /// <returns></returns>
        public int ConvertOpcItemValueInt(OpcDaItemValue item)
        {
            int result = 0;
            if (item.Value is bool)
                result = (Convert.ToBoolean(item.Value) ? 1 : 0);
            else
                int.TryParse(item.Value.ToString(), out result);
            return result;
        }

        public void Server_Shutdown(object sender, OpcShutdownEventArgs e)
        {
            this.opcState = false;
        }

        /// <summary>
        /// 断开opc连接
        /// </summary>
        public void CloseOpcConnetion()
        {
            if (opcServer.IsConnected)
            {
                this.isClose = true;
                opcServer.Disconnect();
                opcServer.Dispose();
            }
        }
        /// <summary>
        /// 状态改变
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Server_ConnectionStateChanged(object sender, OpcDaServerConnectionStateChangedEventArgs e)
        {
            if (e.IsConnected)
            {
                this.opcState = true;
                LogObj.Info("OPC服务已连接");
            }
            else
                this.opcState = false;
            if (!e.IsConnected && isClose == false)
                Task.Factory.StartNew(ReConnectionOpcServer);
        }

        /// <summary>
        /// opc服务自动重连
        /// </summary>
        private async void ReConnectionOpcServer()
        {
            while (true)
            {
                try
                {
                    if (!opcServer.IsConnected)
                        opcServer.Connect();
                    if (opcServer.IsConnected)
                        break;
                }
                catch (Exception ex)
                {
                    LogObj.Error(ex.Message);
                }
                await Task.Delay(3000);
            }
        }

        /// <summary>
        /// 读数据
        /// </summary>
        public OpcDaItemValue[] ReadValue(OpcDaGroup group)
        {
            try
            {

                if (opcServer.IsConnected && group != null && group.IsActive)
                {
                    OpcDaItemValue[] values = group.Read(group.Items, OpcDaDataSource.Device);
                    return values;
                }
            }
            catch (Exception ex)
            {
                LogObj.Error(ex.Message);
            }
            return null;
        }
        /// <summary>
        /// 读数据
        /// </summary>
        public OpcDaItemValue[] ReadValue(OpcDaGroup group, string[] item)
        {
            try
            {

                if (opcServer.IsConnected && group != null && group.IsActive)
                {
                    List<OpcDaItem> list = new List<OpcDaItem>();
                    foreach (var str in item)
                    {
                        var info = group.Items.FirstOrDefault(i => i.ItemId == str);
                        if (info != null)
                            list.Add(info);
                    }

                    OpcDaItemValue[] values = group.Read(list, OpcDaDataSource.Device);
                    return values;
                }
            }
            catch (Exception ex)
            {
                LogObj.Error(ex.Message);
            }
            return null;
        }

        static readonly object opcWriteValueObject = new object();
        /// <summary>
        /// 写数据
        /// </summary>
        public HRESULT[] WriteValue(OpcDaGroup group, IList<string> items, IList<object> values)
        {
            lock (opcWriteValueObject)
            {
                try
                {
                    if (opcServer.IsConnected && group != null && group.IsActive && values != null)
                    {
                        if (items.Count == values.Count)
                        {
                            List<OpcDaItem> list = new List<OpcDaItem>();
                            foreach (var str in items)
                            {
                                var info = group.Items.FirstOrDefault(i => i.ItemId == str);
                                if (info != null)
                                    list.Add(info);
                            }
                            HRESULT[] results = group.Write(list, values.ToArray());
                            return results;
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogObj.Error(ex.Message);
                }
                return null;
            }
        }
        /// <summary>
        /// 更新组中的所有数据
        /// </summary>
        /// <param name="group"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public HRESULT[] WriteValueAll(OpcDaGroup group, object[] values)
        {
            try
            {
                if (opcServer.IsConnected && group != null && group.IsActive)
                {
                    HRESULT[] results = group.Write(group.Items, values.ToArray());
                    return results;
                }
            }
            catch (Exception ex)
            {
                LogObj.Error(ex.Message);
            }
            return null;
        }
    }
}
